﻿#include<iostream>
using namespace std;


////模板参数包
//template<class ...T>
////函数参数包
//void Print(T...ag)
//{
//	cout << sizeof...(ag) << endl;
//	// 可变参数模版编译时解析
//	// 下面是运行获取和解析，所以不支持这样用
//	//for (size_t i = 0; i < sizeof...(args); i++)
//	//{
//	//	cout << args[i] << " ";
//	//}
//
//}

//void print()
//{
//	cout << endl;
//}
//
//template<class T,class ...arg>
//void print(T&& x, arg&&... gt)
//{
//	cout << x << " ";
//	print(gt...);
//}
////编译时递归推导解析参数
//template<class ...arg>
//void add(arg&&...gt)
//{
//	print(gt...);
//}
//
//int main()
//{
//	double x = 2.2;
//
//	add(); // 包⾥有0个参数 
//	add(1); // 包⾥有1个参数 
//	add(1, string("xxxxx")); // 包⾥有2个参数 
//	add(1.1, string("xxxxx"), x); // 包⾥有3个参数 
//
//
//
//	return 0;
//}

//template<class T>
//int print(T t)
//{
//	cout << t << " ";
//	return 0;
//}
////编译推演生成下面的函数
//void add(int x, char y, std::string z)
//{
//	int arr[] = { print(x),print(y),print(z) };
//	cout << endl;
//}

template<class ...arg>
void add(arg... gt)
{
	int arr[] = { (cout << (gt) << " ",0)...};
	cout << endl;
}
//编译推演生成下面的函数
//void ShowList(int x, char y, std::string z)
//{
//	int arr[] = { (cout<<(x)<<" ", 0), (cout << (y) << " ", 0), (cout << (z) << " ", 0) };
//
//	cout << endl;
//}

int main()
{

	add(1, 'n',string("xxxxx")); // 包⾥有2个参数 

	return 0;

}

//void Print()
//{
//	cout << endl;
//}
//
//// 编译器推导的
//void Print(double x)
//{
//	cout << x << " ";
//	Print();
//}
//
//void Print(const char* x, double z)
//{
//	cout << x << " ";
//	Print(z);
//}
//
//void Print(int x, const char* y, double z)
//{
//	cout << x << " ";
//	Print(y, z);
//}
//


// 可变模板参数 
// 参数类型可变 
// 参数个数可变 
// 打印参数包内容 
//template <class ...Args>
//void Print(Args... args)
//{
// // 可变参数模板编译时解析 
// // 下⾯是运⾏获取和解析，所以不⽀持这样⽤ 
// cout << sizeof...(args) << endl;
// for (size_t i = 0; i < sizeof...(args); i++)
// {
// cout << args[i] << " ";
// }
// cout << endl;
//}
void ShowList()
{
	// 编译器时递归的终⽌条件，参数包是0个时，直接匹配这个函数 
	cout << endl;
}
template <class T, class ...Args>
void ShowList(T x, Args... args)
{
	cout << x << " ";
	// args是N个参数的参数包 
	// 调⽤ShowList，参数包的第⼀个传给x，剩下N-1传给第⼆个参数包 
	ShowList(args...);
}
// 编译时递归推导解析参数 
template <class ...Args>
void Print(Args... args)
{
	ShowList(args...);
}
int main()
{
	Print();
	Print(1);
	Print(1, string("xxxxx"));
	Print(1, string("xxxxx"), 2.2);
	return 0;
}
//template <class T, class ...Args>
//void ShowList(T x, Args... args)
//{
// cout << x << " ";
// Print(args...);
//}
// Print(1, string("xxxxx"), 2.2);调⽤时 
// 本质编译器将可变参数模板通过模式的包扩展，编译器推导的以下三个重载函数函数 
//void ShowList(double x)
//{
// cout << x << " ";
// ShowList();
//}
//
//void ShowList(string x, double z)
//{
// cout << x << " ";
// ShowList(z);
//}
//
//void ShowList(int x, string y, double z)
//{
// cout << x << " ";
// ShowList(y, z);
//}
//void Print(int x, string y, double z)
//{
// ShowList(x, y, z);
//}

//template <class T>
//const T& GetArg(const T& x)
//{
//	cout << x << " ";
//	return x;
//}
//template <class ...Args>
//void Arguments(Args... args)
//{
//}
//template <class ...Args>
//void Print(Args... args)
//{
//	// 注意GetArg必须返回或者到的对象，这样才能组成参数包给Arguments 
//	Arguments(GetArg(args)...);
//}
//// 本质可以理解为编译器编译时，包的扩展模式 
//// 将上⾯的函数模板扩展实例化为下⾯的函数 
//// 是不是很抽象，C++11以后，只能说委员会的⼤佬设计语法思维跳跃得太厉害 
////void Print(int x, string y, double z)
////{
//// Arguments(GetArg(x), GetArg(y), GetArg(z));
////}
//
//int main()
//{
//	Print(1, string("xxxxx"), 2.2);
//	return 0;
//}
